#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/4/5 2:56 PM
# @Author  : qichen

# 核保模块
import asyncio
import re
import traceback
import os
import pandas as pd
from bot.insurance_planner_gpt.user_info import UserInfo
from common.log import logger
from knowledge_base.knowledge_embedding import BGEQuery
import pandas as pd
import os
import itertools
from collections import defaultdict
from langchain.schema import Document
from knowledge_base.document_search import get_products_name, get_products_introduction
from bot.insurance_planner_gpt.utils.user_info_util import CandidateProducts
from bot.insurance_planner_gpt.utils.standard_terms_util import StandardTerms
from bot.insurance_planner_gpt.utils.user_info_util import ProfessCate
from bot.insurance_planner_gpt.utils.user_info_util import City
from bot.insurance_planner_gpt.utils.user_info_util import HealthCate
from bot.insurance_planner_gpt.utils.user_info_util import get_nth_age



class InsuranceUnderwriting:
    # 获取保险产品配置
    # products_config_df = pd.read_csv('../doc/products_config.csv', encoding='utf-8')
    current_script_path = os.path.abspath(__file__)
    csv_file_path = os.path.normpath(os.path.join(current_script_path, '../../doc/products_config.csv'))
    products_config_df = pd.read_csv(csv_file_path, encoding='utf-8')
    products_config_df.fillna('', inplace=True)
    products_config_df = products_config_df.set_index('产品名称')
    products_config = products_config_df.to_dict(orient='index')
    # 用户信息提取工具类
    profess_cate = ProfessCate()
    city = City()
    health_cate = HealthCate()

    #

    def __init__(self):
        self.insurance_person_info= ''

    async def get_insurance_person_info(self, user_info):
        """获取被保人的基础信息，用于核保"""
        insurance_person_info = {'被保人':'','是否有社保': '', '年龄': '', '健康类别': '',
                                 '职业类别': '', '地区': '', '目的地': ''}
        try:
            if user_info:
                insurance_person_info['被保人'] = user_info.get('被保人', '本人')
                insurance_person_info['地区'] = self.city.extract_city(str(user_info.get('地区', '')))
                insurance_person_info['目的地'] = str(user_info.get('目的地', ''))
                # TODO 存在年龄是数组的情况这里默认取第一个年龄，并且此处给了默认的年龄
                if insurance_person_info['被保人']  in ['父母', '爷爷', '奶奶', '外公', '外婆']:
                    insurance_person_info['年龄'] = get_nth_age(user_info.get('父母年龄', '50'))
                    insurance_person_info['职业类别'] = self.profess_cate.get_profess_cate(str(user_info.get('父母职业', '')))
                    insurance_person_info['健康类别'] = self.health_cate.get_health_cate(str(user_info.get('父母健康状况', '')))
                    insurance_person_info['是否有社保'] = user_info.get('父母是否有社保', '有')
                elif insurance_person_info['被保人']  == '配偶':
                    insurance_person_info['年龄'] = get_nth_age(user_info.get('配偶年龄', '30'))
                    insurance_person_info['职业类别'] = self.profess_cate.get_profess_cate(str(user_info.get('配偶职业', '')))
                    insurance_person_info['健康类别'] = self.health_cate.get_health_cate(str(user_info.get('配偶健康状况', '')))
                    insurance_person_info['是否有社保'] = user_info.get('配偶是否有社保', '有')
                elif insurance_person_info['被保人']  in ['孩子', '孙子', '孙女']:
                    insurance_person_info['年龄'] = get_nth_age(user_info.get('孩子年龄', '15'))
                    insurance_person_info['职业类别'] = self.profess_cate.get_profess_cate(str(user_info.get('孩子职业', '')))
                    insurance_person_info['健康类别'] = self.health_cate.get_health_cate(str(user_info.get('孩子健康状况', '')))
                    insurance_person_info['是否有社保'] = user_info.get('孩子是否有社保', '有')
                else:
                    insurance_person_info['年龄'] = user_info.get('本人年龄', '30')
                    insurance_person_info['职业类别'] = self.profess_cate.get_profess_cate(str(user_info.get('本人职业', '')))
                    insurance_person_info['健康类别'] = self.health_cate.get_health_cate(str(user_info.get('本人健康状况', '')))
                    insurance_person_info['是否有社保'] = user_info.get('本人是否有社保', '有')
            logger.info(f"【核保模块-用户信息】：获取被保人的基础信息如下： {insurance_person_info}")
            self.insurance_person_info = insurance_person_info
        except Exception:
            logger.error(f"【核保模块异常】：获取被保人的基础信息异常{traceback.format_exc()}")
        return insurance_person_info

    async def check_product_available(self, product_name, insurance_person_info):
        """查找该产品是否可用，如果不可用则给出原因"""
        unavailable_reason = ''
        if_available = True
        try:
            product_config = self.products_config.get(product_name, '')
            if product_config:
                if product_config['是否在售'] == 0:
                    unavailable_reason = unavailable_reason + '该产品已停售,'
                if insurance_person_info['年龄'] != '':
                    age = int(insurance_person_info['年龄'])
                    if age < product_config['年龄下限'] or age > product_config['年龄上限']:
                        if_available = False
                        unavailable_reason = unavailable_reason + '年龄不符,'
                if insurance_person_info['职业类别'] != '' and product_config['职业类别'] != '':
                    if insurance_person_info['职业类别'] not in product_config['职业类别']:
                        if_available = False
                        unavailable_reason = unavailable_reason + '职业类别不符,'
                if insurance_person_info['地区'] != '' and product_config['可买地区'] != '':
                    # TODO 只支持中国大陆的匹配，默认为空的都是中国大陆
                    if insurance_person_info['地区'] not in product_config['可买地区']:
                        if_available = False
                        unavailable_reason = unavailable_reason + '所在地区不符,'
                if insurance_person_info['健康类别'] != '':
                    if_available = await self.check_health_available(insurance_person_info['健康类别'],product_config['健康要求'])
                    if not if_available:
                        unavailable_reason = unavailable_reason + '健康情况不符,'
                if insurance_person_info['目的地'] != '':
                    if_available = await self.check_destination_available(insurance_person_info['目的地'],product_config['保险产品类型'])
                    if not if_available:
                        unavailable_reason = unavailable_reason + '该产品不保'+insurance_person_info['目的地']+','
                if insurance_person_info['是否有社保'] != '':
                    if insurance_person_info['是否有社保']=='否' and  product_config['是否要求社保'] == 1:
                        if_available = False
                        unavailable_reason = unavailable_reason + '该产品要求有社保,'
            if unavailable_reason != '':
                if_available = False
                if unavailable_reason.endswith(','):
                    unavailable_reason = unavailable_reason[:-1]
        except Exception:
            logger.error(f"查找该产品是否可用异常{traceback.format_exc()}")
        return if_available, unavailable_reason

    async def check_destination_available(self, destination_user, destination_product):
        """查找该目的地是否可用，目前只考虑对旅意险中，境外产品的过滤"""
        if_available = True
        try:
            if destination_user == '境外':
                if '境外' not in destination_product:
                    if_available = False
            else:
                if '境外' in destination_product:
                    if_available = False
        except Exception:
            logger.error(f"查找核保异常-目的地{traceback.format_exc()}")
        return if_available

    async def check_health_available(self, health_cate_user,health_cate_product):
        """根据健康看是否可买该产品"""
        if_available = True
        try:
            if health_cate_user == '日常小病':
                if_available = True
            elif health_cate_user == '健告宽松疾病':
                if health_cate_product in ['无', '宽松']:
                    if_available = True
                else:
                    if_available = False
            elif health_cate_user in ['严重不可保疾病', '未知疾病类型']:
                if health_cate_product in ['无']:
                    if_available = True
                else:
                    if_available = False
        except Exception:
            logger.error(f"查找核保异常-健康{traceback.format_exc()}")
        return if_available

    async def check_history_product_availble(self, history_causal):
        """核查历史的每条因果链里的产品，是否都符合条件"""
        # 按照空行切割 history_causal 成list
        history_causal_list = history_causal.split('\n')
        underwrited_history_causal_list = []
        for causal_item in history_causal_list:
            product_name = ''
            if '（保险产品名称）' in causal_item and '无法购买' not in causal_item:
                if self.insurance_person_info['被保人'] =='' or self.insurance_person_info['被保人'] == '本人':
                    if '被保人' not in causal_item or '本人' in causal_item:
                        product_name  = await self.get_product_name(causal_item)
                elif self.insurance_person_info['被保人'] in causal_item:
                    product_name = await self.get_product_name(causal_item)
            if product_name !='':
                is_available, reason = await self.check_product_available(product_name, self.insurance_person_info)
                if is_available == False:
                    causal_item = causal_item + '-> 无法购买：'+ reason
            underwrited_history_causal_list.append(causal_item)
        # 用 \n 拼接成字符串
        underwrited_history_causal = '\n'.join(underwrited_history_causal_list)
        print('历史因果修改之后：',underwrited_history_causal)
        return underwrited_history_causal

    async def get_product_name(self, solution_plan_causal):
        """获取产品名称"""
        product_name = ''
        try:
            solution_plan_causal = solution_plan_causal.replace("(", "（") \
                .replace(")", "）").replace("-> ", "->").replace(" ->", "->").replace(":", "：")
            idx_1 = solution_plan_causal.rfind('（保险产品名称）')
            idx_0_0 = solution_plan_causal.rfind('->', 0, idx_1)
            if idx_0_0 > 1 and idx_1 > idx_0_0 + 2:
                product_name = solution_plan_causal[idx_0_0 + 2:idx_1]
        except Exception:
            logger.error(f"获取产品名称异常{traceback.format_exc()}")
        return product_name